﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace BinaryzationTest
{
    public partial class Form1 : Form
    {
        string SourceFile;
        //灰度矩阵灵敏度，越高效果越好，但越耗时
        int Sensibility = 1;

        public Form1()
        {
            InitializeComponent();
        }




        private void SelectBtn_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                SourceFile = openFileDialog1.FileName;
                ImgPath.Text = SourceFile;
                SourceImg.BackgroundImage = new Bitmap(SourceFile);
                BinaryzatedImg.BackgroundImage = Img2Gray(new Bitmap(SourceFile));
            }
        }

        //图片灰度化，速度快
        public static unsafe Bitmap Img2Gray(Bitmap curBitmap)
        {
            int width = curBitmap.Width;
            int height = curBitmap.Height;
            Bitmap back = new Bitmap(width, height);
            byte temp;
            Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
            //这种速度最快
            BitmapData bmpData = curBitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);//24位rgb显示一个像素，即一个像素点3个字节，每个字节是BGR分量。Format32bppRgb是用4个字节表示一个像素
            byte* ptr = (byte*)(bmpData.Scan0);
            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width; i++)
                {
                    //ptr[2]为r值，ptr[1]为g值，ptr[0]为b值
                    temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]);
                    back.SetPixel(i, j, Color.FromArgb(temp, temp, temp));
                    ptr += 3; //Format24bppRgb格式每个像素占3字节
                }
                ptr += bmpData.Stride - bmpData.Width * 3;//每行读取到最后“有用”数据时，跳过未使用空间XX
            }
            curBitmap.UnlockBits(bmpData);
            return back;
        }

        //图片灰度化,速度慢
        public static Bitmap Img2Gray2(Bitmap curBitmap)
        {
            int width = curBitmap.Width;
            int height = curBitmap.Height;
            Bitmap back = new Bitmap(width, height);
            int GrayScale = 0;
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    //ptr[2]为r值，ptr[1]为g值，ptr[0]为b值
                    GrayScale = curBitmap.GetPixel(i, j).R * 299 / 1000 + curBitmap.GetPixel(i, j).G * 587 / 1000 + curBitmap.GetPixel(i, j).B * 114 / 1000;
                    back.SetPixel(i, j, Color.FromArgb(GrayScale, GrayScale, GrayScale));
                }
            }
            return back;
        }

        //计算图片像素点归属灰度矩阵位置
        public int GetIndex(int location, int length)
        {
            return location * Sensibility / length;
        }

        public Bitmap Gray2Binaryzation(Bitmap GrayImg)
        {
            int width = GrayImg.Width;
            int height = GrayImg.Height;
            Bitmap back = new Bitmap(width, height);
            
            //灰度矩阵初始化
            Int64[,] GrayScale = new Int64[Sensibility, Sensibility];
            for (int i = 0; i < Sensibility; i++)
            {
                for (int j = 0; j < Sensibility; j++)
                {
                    GrayScale[i,j] = 0;
                }
            }

            //计算灰度矩阵阈值，17/20为阈值调整，取0.85时效果最好；
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    GrayScale[GetIndex(i, width), GetIndex(j, height)] += GrayImg.GetPixel(i, j).R;
                }
            }
            for (int i = 0; i < Sensibility; i++)
            {
                for (int j = 0; j < Sensibility; j++)
                {
                    GrayScale[i, j] = GrayScale[i, j] / width * Sensibility / height * Sensibility * 17 / 20;
                }
            }

            //二值化赋值,大于灰度矩阵阈值的描黑，否则描白。
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    if (GrayImg.GetPixel(i, j).R >= GrayScale[GetIndex(i, width), GetIndex(j, height)])
                        back.SetPixel(i, j, Color.FromArgb(255, 255, 255));
                    else
                        back.SetPixel(i, j, Color.FromArgb(0, 0, 0));
                }
            }
            return back;
        }

        private void BinaryzationBtn_Click(object sender, EventArgs e)
        {
            BinaryzatedImg.BackgroundImage = Gray2Binaryzation(Img2Gray(new Bitmap(SourceFile)));
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Sensibility = (int)SensibilitySelector.Value;
            groupBox2.Width = (this.Width - 60) / 2;
            groupBox3.Width = (this.Width - 60) / 2;
            groupBox3.Location = new Point(groupBox3.Width + 32, groupBox3.Location.Y);
        }

        private void SensibilitySelector_ValueChanged(object sender, EventArgs e)
        {
            Sensibility = (int)SensibilitySelector.Value;
        }
    }
}
